#pragma once

#include "event/loop.hpp"
#include "network/buffer.hpp"
#include "network/byte_stream.hpp"
#include "network/fd.hpp"

#include <functional>

namespace ibox::network {

class BufferedFd : public ByteStream {
public:
    explicit BufferedFd(event::EpollLoop *loop);
    ~BufferedFd() override;

public:
    using WriteCompleteCallback = std::function<void()>;
    using ReadZeroCallback = std::function<void()>;
    using ErrorCallback = std::function<void(int)>;

    enum class State {
        Empty,  //! 未初始化
        Inited, //! 已初始化
        Running //! 正在运行
    };

    enum {
        ReadOnly = 0x01,
        WriteOnly = 0x02,
        ReadWrite = 0x03,
    };

    //! 初始化，并指定发送或是接收功能
    bool initialize(Fd &fd, uint32_t events = ReadWrite);

    //! 设置完成了当前数据发送时的回调函数
    void set_send_complete_callback(WriteCompleteCallback cb) {
        m_send_complete_cb = std::move(cb);
    }
    //! 设置当读到0字节数据时回调函数
    void set_read_zero_callback(ReadZeroCallback cb) {
        m_read_zero_cb = std::move(cb);
    }
    //! 设置当遇到错误时的回调函数
    void set_error_callback(ErrorCallback cb) { m_error_cb = std::move(cb); }

    //! 实现 ByteStream 的接口
    void set_receive_callback(ReceiveCallback cb, size_t threshold) override;
    bool send(const void *data_ptr, size_t data_size) override;
    void bind(ByteStream *receiver) override { m_receiver = receiver; }
    void unbind() override { m_receiver = nullptr; }

    //! 启动与关闭内部事件驱动机制
    bool enable();
    bool disable();

    //! 缩减缓冲，防止长期占用大空间内存
    void shrink_recv_buffer();
    void shrink_send_buffer();

    inline Fd fd() const { return m_fd; }
    inline State state() const { return m_state; }

private:
    void on_read_callback(uint32_t);
    void on_write_callback(uint32_t);

private:
    event::EpollLoop *m_loop = nullptr; //! 事件驱动

    Fd m_fd;
    State m_state = State::Empty;

    std::unique_ptr<event::EpollFdEvent> m_read_event{};
    std::unique_ptr<event::EpollFdEvent> m_write_event{};

    Buffer m_send_buff;
    Buffer m_recv_buff;

    ReceiveCallback m_receive_cb;
    WriteCompleteCallback m_send_complete_cb;
    ReadZeroCallback m_read_zero_cb;
    ErrorCallback m_error_cb;

    ByteStream *m_receiver = nullptr;

    size_t m_receive_threshold = 0;
};

} // namespace ibox::network
